package uva.sc.ql.evaluator;
import java.util.Map;
import uva.sc.ql.ast.IQLExpressionNodeVisitor;
import uva.sc.ql.atom.BooleanAtom;
import uva.sc.ql.atom.ID;
import uva.sc.ql.atom.NumberAtom;
import uva.sc.ql.atom.StringAtom;
import uva.sc.ql.expression.Expression;
import uva.sc.ql.expression.binaryExpressions.Addition;
import uva.sc.ql.expression.binaryExpressions.And;
import uva.sc.ql.expression.binaryExpressions.Division;
import uva.sc.ql.expression.binaryExpressions.Equals;
import uva.sc.ql.expression.binaryExpressions.GreaterThan;
import uva.sc.ql.expression.binaryExpressions.GreaterThanEquals;
import uva.sc.ql.expression.binaryExpressions.LesserThan;
import uva.sc.ql.expression.binaryExpressions.LesserThanEquals;
import uva.sc.ql.expression.binaryExpressions.Modulus;
import uva.sc.ql.expression.binaryExpressions.Multiplication;
import uva.sc.ql.expression.binaryExpressions.NotEquals;
import uva.sc.ql.expression.binaryExpressions.Or;
import uva.sc.ql.expression.binaryExpressions.Substraction;
import uva.sc.ql.expression.unaryExpressions.Minus;
import uva.sc.ql.expression.unaryExpressions.Not;
import uva.sc.ql.gui.helpers.QuestionData;
/**
* Evaluates expressions using a values table.
*
* @author Pantelis & Satiago
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class EvaluatorVisitor implements IQLExpressionNodeVisitor<Expression> {
private Map<ID, QuestionData> valuesTable;
public EvaluatorVisitor(Map<ID, QuestionData> valuesTable) {
this.valuesTable = valuesTable;
}
public Expression evaluateExpression(Expression expr) {
return (Expression) expr.accept(this);
}
private QuestionData questionData(ID id) {
return valuesTable.get(id);
}
public Expression visit(ID id) {
return questionData(id).getValue();
}
public NumberAtom visit(Addition addition) {
NumberAtom firstOperand = getNumericOperandValue((Expression) addition
.getFirstOperand().accept(this));
NumberAtom secondOperand = getNumericOperandValue((Expression) addition
.getSecondOperand().accept(this));
return new NumberAtom(firstOperand.getValue()
+ secondOperand.getValue());
}
public NumberAtom visit(Substraction substraction) {
NumberAtom firstOperand = getNumericOperandValue((Expression) substraction
.getFirstOperand().accept(this));
NumberAtom secondOperand = getNumericOperandValue((Expression) substraction
.getSecondOperand().accept(this));
return new NumberAtom(firstOperand.getValue()
- secondOperand.getValue());
}
public NumberAtom visit(Multiplication multiplication) {
NumberAtom firstOperand = getNumericOperandValue((Expression) multiplication
.getFirstOperand().accept(this));
NumberAtom secondOperand = getNumericOperandValue((Expression) multiplication
.getSecondOperand().accept(this));
return new NumberAtom(firstOperand.getValue()
* secondOperand.getValue());
}
public NumberAtom visit(Division division) {
NumberAtom firstOperand = getNumericOperandValue((Expression) division
.getFirstOperand().accept(this));
NumberAtom secondOperand = getNumericOperandValue((Expression) division
.getSecondOperand().accept(this));
NumberAtom result = new NumberAtom(0.);
try {
result = new NumberAtom(firstOperand.getValue()
/ secondOperand.getValue());
} catch (ArithmeticException e) {
}
return result;
}
public NumberAtom visit(Modulus modulus) {
NumberAtom firstOperand = getNumericOperandValue((Expression) modulus
.getFirstOperand().accept(this));
NumberAtom secondOperand = getNumericOperandValue((Expression) modulus
.getSecondOperand().accept(this));
NumberAtom result = new NumberAtom(0.);
try {
result = new NumberAtom(firstOperand.getValue()
% secondOperand.getValue());
} catch (ArithmeticException e) {
}
return result;
}
public BooleanAtom visit(And and) {
BooleanAtom firstOperand = (BooleanAtom) and.getFirstOperand().accept(
this);
BooleanAtom secondOperand = (BooleanAtom) and.getSecondOperand()
.accept(this);
BooleanAtom result = new BooleanAtom(false);
if (firstOperand != null && secondOperand != null) {
result = new BooleanAtom(java.lang.Boolean.valueOf(firstOperand
.getValue())
&& java.lang.Boolean.valueOf(secondOperand.getValue()));
}
return result;
}
public BooleanAtom visit(Or or) {
BooleanAtom firstOperand = (BooleanAtom) or.getFirstOperand().accept(
this);
BooleanAtom secondOperand = (BooleanAtom) or.getSecondOperand().accept(
this);
BooleanAtom result = new BooleanAtom(false);
if (firstOperand != null && secondOperand != null) {
result = new BooleanAtom(java.lang.Boolean.valueOf(firstOperand
.getValue())
|| java.lang.Boolean.valueOf(secondOperand.getValue()));
}
return result;
}
public BooleanAtom visit(Equals equals) {
Expression firstOperand = (Expression) equals.getFirstOperand()
.accept(this);
Expression secondOperand = (Expression) equals.getSecondOperand().accept(
this);
return new BooleanAtom(firstOperand.getValue().equals(
secondOperand.getValue()));
}
public BooleanAtom visit(NotEquals notEquals) {
Expression firstOperand = (Expression) notEquals.getFirstOperand()
.accept(this);
Expression secondOperand = (Expression) notEquals.getSecondOperand()
.accept(this);
return new BooleanAtom(!firstOperand.getValue().equals(
secondOperand.getValue()));
}
public BooleanAtom visit(GreaterThan greaterThan) {
NumberAtom firstOperand = getNumericOperandValue((Expression) greaterThan
.getFirstOperand().accept(this));
NumberAtom secondOperand = getNumericOperandValue((Expression) greaterThan
.getSecondOperand().accept(this));
return new BooleanAtom(firstOperand.getValue().compareTo(
secondOperand.getValue()) == 1);
}
public BooleanAtom visit(GreaterThanEquals greaterThanEquals) {
NumberAtom firstOperand = getNumericOperandValue((Expression) greaterThanEquals
.getFirstOperand().accept(this));
NumberAtom secondOperand = getNumericOperandValue((Expression) greaterThanEquals
.getSecondOperand().accept(this));
return new BooleanAtom(firstOperand.getValue().compareTo(
secondOperand.getValue()) >= 0);
}
public BooleanAtom visit(LesserThan lesserThan) {
NumberAtom firstOperand = getNumericOperandValue((Expression) lesserThan
.getFirstOperand().accept(this));
NumberAtom secondOperand = getNumericOperandValue((Expression) lesserThan
.getSecondOperand().accept(this));
return new BooleanAtom(firstOperand.getValue().compareTo(
secondOperand.getValue()) == -1);
}
public BooleanAtom visit(LesserThanEquals lesserThanEquals) {
NumberAtom firstOperand = getNumericOperandValue((Expression) lesserThanEquals
.getFirstOperand().accept(this));
NumberAtom secondOperand = getNumericOperandValue((Expression) lesserThanEquals
.getSecondOperand().accept(this));
return new BooleanAtom(firstOperand.getValue().compareTo(
secondOperand.getValue()) <= 0);
}
public NumberAtom visit(Minus minus) {
NumberAtom operand = (NumberAtom) minus.getOperand().accept(this);
NumberAtom result = new NumberAtom(0.);
if (operand != null) {
NumberAtom numericalOperand = new NumberAtom(operand.getValue());
result = new NumberAtom(numericalOperand.getValue() * (-1));
}
return result;
}
public BooleanAtom visit(Not not) {
BooleanAtom operand = (BooleanAtom) not.getOperand().accept(this);
return new BooleanAtom(!operand.getValue());
}
public BooleanAtom visit(BooleanAtom bool) {
return bool;
}
public NumberAtom visit(NumberAtom doub) {
return doub;
}
public StringAtom visit(StringAtom str) {
return str;
}
private NumberAtom getNumericOperandValue(Expression expr) {
NumberAtom result = new NumberAtom(0.);
if (expr != null) {
result = new NumberAtom((Double) expr.getValue());
}
return result;
}
}